import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.Map;
import java.util.UUID;

public class Session {
    private static final String LOG_FILE = "session_modify_log.txt";
    private static LinkedList<Session> sessionList = new LinkedList<>();

    private Hall hall;//将影厅Hall与场次Session关联起来
    String movieName;    // 影片名称
    String hallName;     // 影厅名称
    String startTime;    // 开始时间
    String endTime;      // 结束时间
    double price;



    public Session() {}

    public Session(String movieName,  Hall hall, String startTime, String endTime, double price) {
        if (hall == null) {
            throw new IllegalArgumentException("Hall对象不能为null");
        }
        this.movieName = movieName;
        this.hall=hall;
        this.hallName = hall.getHallName();
        this.startTime = startTime;
        this.endTime = endTime;
        this.price = price;
    }

    public static LinkedList<Session> getSessionList() {
        return sessionList;
    }

    public static void setSessionList(LinkedList<Session> sessionList) {
        Session.sessionList = sessionList;
    }

    //新增获取Hall对象的方法
    public Hall getHall() {
        return hall;
    }

    public void setHall(Hall hall) {
        this.hall = hall;
    }
    public String getMovieName() {
        return movieName;
    }

    public void setMovieName(String movieName) {
        this.movieName = movieName;
    }

    public String getHallName() {
        return hallName;
    }

    public void setHallName(String hallName) {
        this.hallName = hallName;
    }

    public String getStartTime() {
        return startTime;
    }

    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }

    public String getEndTime() {
        return endTime;
    }

    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }



    //该方法实现列出所有场次信息
    // ... 其他代码保持不变 ...

    public void listAllSessions() {
        Scanner scanner = new Scanner(System.in);

        System.out.println("\n请选择场次时间范围：");
        System.out.println("1. 当日场次");
        System.out.println("2. 近3日场次");
        System.out.println("3. 最近一周场次");
        System.out.println("4. 自定义天数");
        System.out.print("请输入选择(1-4，默认3): ");
        String choice = scanner.nextLine();

        int days = 7; // 默认最近一周
        if (choice.equals("1")) {
            days = 1;
        } else if (choice.equals("2")) {
            days = 3;
        } else if (choice.equals("4")) {
            System.out.print("请输入要查询的天数: ");
            days = scanner.nextInt();
            scanner.nextLine(); // 消耗换行符
        }

        System.out.println("\n=== 场次信息列表 ===");
        System.out.println("影片名称\t放映厅\t开始时间\t\t结束时间\t\t票价");

        for (Session session : sessionList) {
            if (isWithinDays(session.startTime, days)) {
                System.out.printf("%s\t%s\t%s\t%s\t%.2f元\n",
                        session.movieName, session.hallName,
                        session.startTime, session.endTime, session.price);
            }
        }
    }

    // ... 其他代码保持不变 ...
    // 辅助方法：检查场次是否在指定天数内
    private boolean isWithinDays(String sessionTime, int days) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            Date sessionDate = sdf.parse(sessionTime);
            Date now = new Date();

            // 获取当天0点的时间
            Calendar todayCal = Calendar.getInstance();
            todayCal.setTime(now);
            todayCal.set(Calendar.HOUR_OF_DAY, 0);
            todayCal.set(Calendar.MINUTE, 0);
            todayCal.set(Calendar.SECOND, 0);
            todayCal.set(Calendar.MILLISECOND, 0);
            Date todayStart = todayCal.getTime();

            // 计算结束时间
            todayCal.add(Calendar.DATE, days);
            Date endDate = todayCal.getTime();

            // 检查场次时间是否在当天0点到days天后的0点之间
            return sessionDate.compareTo(todayStart) >= 0 &&
                    sessionDate.compareTo(endDate) < 0;
        } catch (ParseException e) {
            return false;
        }
    }


    //该方式实现增加场次
    public void addSession() {
        Scanner scanner = new Scanner(System.in);

        // 输入影片信息
        System.out.println("\n=== 添加新场次 ===");
        System.out.println("请输入影片名称：");
        String movie = scanner.nextLine();

        // 从Movies类获取电影时长
        int duration = Movies.getMovieDuration(movie);

        // 获取Hall对象而不是名称
        System.out.println("请选择影厅：");
        Hall selectedHall = Hall.selectHall(); // 确保Hall类有选择影厅的方法


        // 输入时间信息
        System.out.println("请输入放映日期(格式：yyyy-MM-dd)：");
        String date = scanner.nextLine();
        System.out.println("请输入开始时间(格式：HH:mm)：");
        String start = scanner.nextLine();
        // 自动计算结束时间
        String end = calculateEndTime(start, duration);


        // 输入价格信息
        System.out.println("请输入本场次票价：");
        double price = scanner.nextDouble();
        scanner.nextLine(); // 消耗换行符


        // 创建新场次并添加到链表
        if (selectedHall != null) {
            sessionList.add(new Session(movie, selectedHall, date + " " + start, date + " " + end, price));
            System.out.println("场次添加成功！");
        } else {
            System.out.println("影厅选择无效，场次添加失败！");
            return;
        }


        // 询问是否继续添加一周场次
        System.out.println("是否要为该影片安排一周的场次？(y/n)");
        if (scanner.nextLine().equalsIgnoreCase("y")) {
            autoScheduleWeek(movie, selectedHall, price, date);
        }
    }
    //辅助方法：该方法实现为影片自动安排一周场次
    private void autoScheduleWeek(String movie, Hall hall, double basePrice, String startDate) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入每日场次数量：");
        int sessionsPerDay = scanner.nextInt();

        System.out.println("请输入场次间隔时间(分钟)：");
        int interval = scanner.nextInt();

        System.out.println("请输入第一个场次的开始时间(格式：HH:mm)：");
        String firstSessionTime = scanner.next();
        scanner.nextLine(); // 消耗换行符

        // 获取工作日和周末基础价格
        System.out.println("请输入工作日基础票价：");
        double weekdayPrice = scanner.nextDouble();
        System.out.println("请输入周末基础票价：");
        double weekendPrice = scanner.nextDouble();
        scanner.nextLine(); // 消耗换行符

        // 获取电影时长(分钟)
        int duration = Movies.getMovieDuration(movie);
        if(duration <= 0) {
            System.out.println("无法获取电影时长，请手动输入电影时长(分钟):");
            duration = scanner.nextInt();
            scanner.nextLine(); // 消耗换行符
            if(duration <= 0) {
                System.out.println("无效时长，使用默认120分钟");
                duration = 120;
            }
        } else {
            System.out.println("已获取电影《" + movie + "》时长: " + duration + "分钟");
        }


        // 解析起始日期
        String[] dateParts = startDate.split("-");
        int year = Integer.parseInt(dateParts[0]);
        int month = Integer.parseInt(dateParts[1]);
        int day = Integer.parseInt(dateParts[2]);

        // 为未来7天安排场次
        for (int i = 0; i < 7; i++) {
            String currentDate = String.format("%04d-%02d-%02d", year, month, day);
            boolean isWeekend = isWeekend(currentDate);

            // 每天重置基础价格
            double dailyBasePrice = isWeekend ? weekendPrice : weekdayPrice;

            // 解析第一个场次时间
            String[] timeParts = firstSessionTime.split(":");
            int startHour = Integer.parseInt(timeParts[0]);
            int startMinute = Integer.parseInt(timeParts[1]);

            for (int j = 0; j < sessionsPerDay; j++) {
                // 计算场次时间
                String startTime = String.format("%02d:%02d", startHour, startMinute);
                String endTime = calculateEndTime(startTime, duration);

                // 计算票价（每天从基础价格开始递增）
                double currentPrice = dailyBasePrice + (j * dailyBasePrice * 0.05); // 每天场次递增5%

                // 添加到场次列表//确保使用传入的hall参数而不是类成员变量
                if (hall != null) {
                    sessionList.add(new Session(movie, hall, currentDate + " " + startTime, currentDate + " " + endTime, currentPrice));
                } else {
                    System.out.println("影厅无效，跳过场次创建");
                    continue;
                }

                // 更新下一个场次时间(开始时间+电影时长+间隔时间)
                startMinute += (duration + interval);
                while (startMinute >= 60) {
                    startHour += 1;
                    startMinute -= 60;
                }
            }

            // 更新日期
            day++;
            if (day > 31) {
                day = 1;
                month++;
                if (month > 12) {
                    month = 1;
                    year++;
                }
            }
        }

        System.out.println("已成功为" + movie + "安排一周场次，共" + (7 * sessionsPerDay) + "场");
    }



    //该方法实现修改场次
    public void modifySession() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("\n=== 修改场次 ===");

        // 1. 先列出所有场次供用户选择
        listAllSessions();

        // 2. 获取用户要修改的场次
        System.out.println("\n请输入要修改的场次编号(从0开始)：");
        int index = scanner.nextInt();
        scanner.nextLine(); // 消耗换行符

        if (index < 0 || index >= sessionList.size()) {
            System.out.println("无效的场次编号！");
            return;
        }

        Session targetSession = sessionList.get(index);

        // 3. 检查是否有票售出
        if (checkTicketsSold(targetSession)) {
            System.out.println("该场次已有票售出，不允许修改！");
            return;
        }

        // 4. 显示当前信息并获取修改内容
        System.out.println("\n当前场次信息：");
        System.out.println("1. 影片名称: " + targetSession.movieName);
        System.out.println("2. 放映厅: " + targetSession.hallName);
        System.out.println("3. 开始时间: " + targetSession.startTime);
        System.out.println("4. 结束时间: " + targetSession.endTime);
        System.out.println("5. 票价: " + targetSession.price);
        System.out.println("0. 完成修改");

        // 记录原始信息
        String originalInfo = targetSession.toString();
        boolean modified = false;

        while (true) {
            System.out.print("\n请输入要修改的项(1-5，0完成): ");
            int choice = scanner.nextInt();
            scanner.nextLine(); // 消耗换行符

            if (choice == 0) {
                break;
            }

            switch (choice) {
                case 1:
                    System.out.print("请输入新影片名称: ");
                    targetSession.movieName = scanner.nextLine();
                    modified = true;
                    break;
                case 2:
                    System.out.print("请输入新放映厅: ");
                    targetSession.hallName = scanner.nextLine();
                    modified = true;
                    break;
                case 3:
                    System.out.print("请输入新开始时间(yyyy-MM-dd HH:mm): ");
                    targetSession.startTime = scanner.nextLine();
                    modified = true;
                    break;
                case 4:
                    System.out.print("请输入新结束时间(yyyy-MM-dd HH:mm): ");
                    targetSession.endTime = scanner.nextLine();
                    modified = true;
                    break;
                case 5:
                    System.out.print("请输入新票价: ");
                    targetSession.price = scanner.nextDouble();
                    scanner.nextLine(); // 消耗换行符
                    modified = true;
                    break;
                default:
                    System.out.println("无效选择！");
            }
        }

        // 5. 记录日志并保存
        if (modified) {
            recordOperationLog("修改场次", "从: " + originalInfo + " 修改为: " + targetSession.toString());
            System.out.println("场次修改成功！");
        } else {
            System.out.println("未做任何修改。");
        }
    }


    //该方法实现删除场次
    public void deleteSession() {
        Scanner scanner = new Scanner(System.in);
        // 1. 先列出所有场次供用户选择
        listAllSessions();
        // 2. 获取用户要删除的场次
        System.out.println("\n请输入要删除的场次编号(从0开始)：");
        int index = scanner.nextInt();
        scanner.nextLine(); // 消耗换行符
        if (index < 0 || index >= sessionList.size()) {
            System.out.println("无效的场次编号！");
            return;
        }
        Session targetSession = sessionList.get(index);
        // 3. 检查是否有票售出
        if (checkTicketsSold(targetSession)) {
            System.out.println("该场次已有票售出，不允许删除！");
            return;
        }
        // 4. 确认删除
        System.out.println("\n即将删除以下场次：");
        System.out.println("影片：" + targetSession.movieName);
        System.out.println("影厅：" + targetSession.hallName);
        System.out.println("时间：" + targetSession.startTime + " - " + targetSession.endTime);
        System.out.println("票价：" + targetSession.price);
        System.out.println("\n确认删除？(y/n)");
        if (!scanner.nextLine().equalsIgnoreCase("y")) {
            System.out.println("取消删除操作");
            return;
        }

        // 5. 执行删除
        sessionList.remove(index);
        // 记录更详细的删除日志
        String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        String logDetail = String.format("删除场次 - 影片: %s, 场次时间: %s", targetSession.movieName, targetSession.startTime);
        recordOperationLog("删除场次", logDetail);

        System.out.println("场次删除成功！");
    }


    //该方法实现自动排片功能
    public void autoSchedule() {
        // 1. 获取未来一周未排片的电影
        LinkedList<Movies> unscheduledMovies = Movies.getUnscheduledMovies();

        if (unscheduledMovies.isEmpty()) {
            System.out.println("没有需要自动排片的电影");
            return;
        }

        System.out.println("=== 开始自动排片 ===");
        System.out.println("共发现" + unscheduledMovies.size() + "部电影需要排片");

        // 2. 按评分排序电影(降序)
        unscheduledMovies.sort((m1, m2) -> Double.compare(m2.getScore(), m1.getScore()));

        // 3. 获取所有可用影厅
        LinkedList<Hall> availableHalls = Hall.getAllHalls();
        if (availableHalls.isEmpty()) {
            System.out.println("没有可用影厅，排片失败");
            return;
        }

        // 4. 为未来7天排片
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String today = sdf.format(new Date());

        for (int day = 0; day < 7; day++) {
            String date = getDateAfterDays(today, day);
            boolean isWeekend = isWeekend(date);

            // 根据星期几分配不同时段
            String[][] timeSlots = getTimeSlotsForDay(isWeekend);

            // 为每个时段安排电影
            int hallIndex = 0;
            for (String[] slot : timeSlots) {
                if (unscheduledMovies.isEmpty()) break;

                Movies movie = unscheduledMovies.get(0);
                Hall hall = availableHalls.get(hallIndex % availableHalls.size());
                hallIndex++;

                // 计算结束时间
                int duration = movie.getDuration();
                String startTime = date + " " + slot[0];
                String endTime = calculateEndTime(slot[0], duration);

                // 根据时段和评分设置票价
                double price = calculatePrice(isWeekend, slot[1], movie.getScore());

                // 添加场次
                sessionList.add(new Session(movie.getName(), hall, startTime, date + " " + endTime, price));

                // 如果是高评分电影，优先安排多个场次
                if (movie.getScore() < 8.0) {
                    unscheduledMovies.remove(0);
                }
            }
        }

        System.out.println("=== 自动排片完成 ===");
    }

    // 辅助方法：根据星期几和评分获取时间段
    private String[][] getTimeSlotsForDay(boolean isWeekend) {
        if (isWeekend) {
            // 周末：更多黄金时段
            return new String[][]{
                    {"10:00", "morning"},
                    {"13:00", "afternoon"},
                    {"15:30", "afternoon"},
                    {"18:00", "evening"},
                    {"20:30", "evening"}
            };
        } else {
            // 工作日：主要是晚间场次
            return new String[][]{
                    {"12:00", "noon"},
                    {"18:30", "evening"},
                    {"21:00", "late"}
            };
        }
    }

    // 辅助方法：计算票价
    private double calculatePrice(boolean isWeekend, String timeSlot, double rating) {
        double basePrice = 35.0;

        // 周末加价
        if (isWeekend) basePrice += 10;

        // 时段加价
        switch (timeSlot) {
            case "evening": basePrice += 15;
                break;
            case "afternoon": basePrice += 5;
                break;
            case "late": basePrice -= 5;
                break;
        }

        // 评分加价
        if (rating >= 9.0) basePrice += 10;
        else if (rating >= 8.0) basePrice += 5;

        return Math.round(basePrice * 100) / 100.0; // 保留两位小数
    }

    // Add helper method to get unscheduled movies
    private LinkedList<Movies> getUnscheduledMovies() {
        LinkedList<Movies> allMovies = Movies.getAllMovies();
        LinkedList<Movies> unscheduled = new LinkedList<>();

        // Get date range for next 7 days
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String today = sdf.format(new Date());
        String endDate = getDateAfterDays(today, 7);

        for (Movies movie : allMovies) {
            boolean hasScheduled = false;

            // Check if movie already has scheduled sessions
            for (Session session : Session.getSessionList()) {
                if (session.getMovieName().equals(movie.getName()) &&
                        session.getStartTime().compareTo(today) >= 0 &&
                        session.getStartTime().compareTo(endDate) < 0) {
                    hasScheduled = true;
                    break;
                }
            }

            if (!hasScheduled) {
                unscheduled.add(movie);
            }
        }

        return unscheduled;
    }


    // 该方法实现自动排片功能 - 重载版本：指定电影排片
    public void autoSchedule(String targetMovieName) {
        // 1. 查找指定电影
        Movies targetMovie = null;
        for (Movies movie : Movies.getAllMovies()) {
            if (movie.getName().equals(targetMovieName)) {
                targetMovie = movie;
                break;
            }
        }

        if (targetMovie == null) {
            System.out.println("未找到电影: " + targetMovieName);
            return;
        }

        // 2. 检查该电影是否已有排片
        boolean hasScheduled = false;
        for (Session s : sessionList) {
            if (s.movieName.equals(targetMovieName)) {
                hasScheduled = true;
                break;
            }
        }

        if (hasScheduled) {
            System.out.println("电影《" + targetMovieName + "》已有排片，无法重复排片");
            return;
        }

        // 3. 创建只包含目标电影的排片列表
        LinkedList<Movies> targetMovies = new LinkedList<>();
        targetMovies.add(targetMovie);

        System.out.println("=== 开始为指定电影自动排片 ===");
        System.out.println("为电影《" + targetMovieName + "》排片");

        // 4. 获取所有可用影厅
        LinkedList<Hall> availableHalls = Hall.getAllHalls();
        if (availableHalls.isEmpty()) {
            System.out.println("没有可用影厅，排片失败");
            return;
        }

        // 5. 为未来7天排片 (复用原有逻辑)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String today = sdf.format(new Date());

        for (int day = 0; day < 7; day++) {
            String date = getDateAfterDays(today, day);
            boolean isWeekend = isWeekend(date);
            String[][] timeSlots = getTimeSlotsForDay(isWeekend);

            int hallIndex = 0;
            for (String[] slot : timeSlots) {
                Hall hall = availableHalls.get(hallIndex % availableHalls.size());
                hallIndex++;

                int duration = targetMovie.getDuration();
                String startTime = date + " " + slot[0];
                String endTime = calculateEndTime(slot[0], duration);
                double price = calculatePrice(isWeekend, slot[1], targetMovie.getScore());

                sessionList.add(new Session(targetMovie.getName(), hall, startTime, date + " " + endTime, price));
                break; // 每个时段只安排一场
            }
        }

        System.out.println("=== 指定电影自动排片完成 ===");
    }

    // 辅助方法：计算n天后的日期
    private String getDateAfterDays(String date, int days) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date d = sdf.parse(date);
            d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
            return sdf.format(d);
        } catch (ParseException e) {
            return date;
        }
    }
    // 辅助方法：判断是否是周末
    private boolean isWeekend(String date) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date d = sdf.parse(date);
            Calendar cal = Calendar.getInstance();
            cal.setTime(d);
            int day = cal.get(Calendar.DAY_OF_WEEK);
            return day == Calendar.SATURDAY || day == Calendar.SUNDAY;
        } catch (ParseException e) {
            return false;
        }
    }
    // 辅助方法：计算结束时间(假设电影时长2小时)
    private String getEndTime(String startTime) {
        String[] parts = startTime.split(":");
        int hour = Integer.parseInt(parts[0]) + 2;
        return String.format("%02d:%02d", hour, Integer.parseInt(parts[1]));
    }


    // 添加检查票是否售出的方法
    public boolean checkTicketsSold(Session session) {
        Map<UUID, Sales.TicketInfo> soldTickets = TicketSellingFunction.getSoldTickets();
        for (Sales.TicketInfo ticket : soldTickets.values()) {
            if (ticket.sessionTime.equals(session.getStartTime()) &&
                    ticket.movieName.equals(session.getMovieName())) {
                return true;
            }
        }
        return false;
    }

    //辅助方法：该方法实现记录电影排片的操作日志
    private void recordOperationLog(String operationType, String operationDetail) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入操作人姓名：");
        String operator = scanner.nextLine();

        String timestamp = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date());
        String logEntry = String.format("[%s] 操作类型: %s, 操作人: %s, 详细信息: %s", timestamp, operationType, operator, operationDetail);

        try (java.io.PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(LOG_FILE, true))) {
            out.println(logEntry);
        } catch (java.io.IOException e) {
            System.err.println("无法写入日志文件: " + e.getMessage());
        }
    }

    // 新增辅助方法：根据开始时间和电影时长计算结束时间
    private String calculateEndTime(String startTime, int durationMinutes) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            Date start = sdf.parse(startTime);
            Calendar cal = Calendar.getInstance();
            cal.setTime(start);
            cal.add(Calendar.MINUTE, durationMinutes);
            return sdf.format(cal.getTime());
        } catch (ParseException e) {
            System.out.println("时间格式错误，使用默认2小时时长");
            String[] parts = startTime.split(":");
            int hour = Integer.parseInt(parts[0]) + 2;
            return String.format("%02d:%02d", hour, Integer.parseInt(parts[1]));
        }
    }

    // 添加静态方法：清空会话修改日志文件
    public static void clearLogFile() {
        try {
            java.nio.file.Files.write(
                    java.nio.file.Paths.get(LOG_FILE),
                    new byte[0],
                    java.nio.file.StandardOpenOption.TRUNCATE_EXISTING
            );
            System.out.println("会话修改日志已清空");
        } catch (java.io.IOException e) {
            System.err.println("清空会话修改日志失败: " + e.getMessage());
        }
    }
}



